package com.chatplus.application.controller.api;

import cn.dev33.satoken.annotation.SaIgnore;
import com.chatplus.application.common.exception.BadRequestException;
import com.chatplus.application.common.logging.SouthernQuietLogger;
import com.chatplus.application.common.logging.SouthernQuietLoggerFactory;
import com.chatplus.application.domain.dto.AdminConfigDto;
import com.chatplus.application.domain.entity.account.UserEntity;
import com.chatplus.application.domain.entity.account.WechatUserEntity;
import com.chatplus.application.enumeration.WechatUserStatusEnum;
import com.chatplus.application.service.account.UserService;
import com.chatplus.application.service.auth.authentication.UserAuthenticationService;
import com.chatplus.application.service.auth.request.AccountAuthenticationRequest;
import com.chatplus.application.service.wxmp.handler.SubscribeHandler;
import com.chatplus.application.service.wxmp.impl.WeChatMpService;
import com.chatplus.application.util.ConfigUtil;
import com.chatplus.application.util.ToUrlParamsUtils;
import com.chatplus.application.web.util.IpUtil;
import jakarta.servlet.http.HttpServletRequest;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

/**
 * 第三方认证控制器
 *
 * @author chj
 * @date 2024/6/3
 **/
@RequestMapping("/api/social")
@Controller
public class SocialAuthController {

    static final SouthernQuietLogger LOGGER = SouthernQuietLoggerFactory.getLogger(SocialAuthController.class);
    private final WeChatMpService weChatMpService;
    private final SubscribeHandler subscribeHandler;
    private final UserService usersService;
    private final UserAuthenticationService userAuthenticationService;


    public SocialAuthController(WeChatMpService weChatMpService,
                                SubscribeHandler subscribeHandler,
                                UserService usersService,
                                UserAuthenticationService userAuthenticationService) {
        this.weChatMpService = weChatMpService;
        this.subscribeHandler = subscribeHandler;
        this.usersService = usersService;
        this.userAuthenticationService = userAuthenticationService;
    }

    /**
     * 微信授权回调
     */
    @RequestMapping("/wechatMpCallback")
    @SaIgnore
    public ModelAndView wechatCallback(@RequestParam String code, HttpServletRequest request) {
        AdminConfigDto adminConfigDto = ConfigUtil.getAdminConfig();
        String url = adminConfigDto.getBaseFrontendUrl();
        try {
            WxOAuth2AccessToken accessToken = weChatMpService.getOAuth2Service().getAccessToken(code);
            String openId = accessToken.getOpenId();
            String appId = weChatMpService.getWxMpConfigStorage().getAppId();
            WxMpUser wxMpUser = weChatMpService.getUserService().userInfo(openId, null);
            LOGGER.message("微信授权回调").context("wxMpUser", wxMpUser).info();  // 记录日志
            WechatUserEntity wechatUserEntity = subscribeHandler.handleUser(appId, openId, WechatUserStatusEnum.FOLLOWED);
            if (wechatUserEntity != null) {
                Long userId = wechatUserEntity.getUserId();
                UserEntity userEntity = usersService.getById(userId);
                if (userEntity == null) {
                    throw new BadRequestException("用户不存在：" + userId);
                }
                AccountAuthenticationRequest accountAuthenticationRequest = new AccountAuthenticationRequest();
                accountAuthenticationRequest.setUsername(userEntity.getUsername());
                accountAuthenticationRequest.setPassword(userEntity.getPassword());
                accountAuthenticationRequest.setRemoteIp(IpUtil.getRemoteIp(request));
                String token = userAuthenticationService.authenticate(accountAuthenticationRequest).getAuthorizationToken();
                url = ToUrlParamsUtils.addParamToUrl(url, "token", token);
            }
            LOGGER.message("授权获取用户信息成功").context("url", url).info();
            return new ModelAndView("redirect:" + url);
        } catch (WxErrorException e) {
            LOGGER.message("授权获取用户信息异常").exception(e).error();
        }
        return new ModelAndView("redirect:" + url);
    }
}
